home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_09_07 / 9n07086a < prev    next >
Text File  |  1991-02-12  |  3KB  |  90 lines

  1.  
  2. #include <ctype.h>
  3. #include <errno.h>
  4. #include <math.h>
  5. #include "float.h"
  6. #ifndef errno
  7. extern int errno;
  8. #endif
  9. extern struct {
  10.     double n[308];
  11.     double p[DBL_MAX_10_EXP + 1];
  12. }      dp10_;
  13.  
  14.  
  15. double atof(dstr)
  16.     char *dstr;                 /* any correctly working atof() may be used */
  17. {
  18.     int c,                      /* difference from exponent of accumulated
  19.                                    integer to final value */
  20.         exp = 0, neg_val = 0,   /* leading negative sign ? */
  21.         e_exp = 0,              /* number after e/E +/- */
  22.         neg_exp = 0,            /* - after E/e ? */
  23.         fdig = 0;
  24. #ifdef __STDC__
  25.     long double x, retval = 0, r = 0;
  26. #else
  27.     register double x, retval = 0, r = 0;
  28. #endif
  29.     while (isspace(c = *dstr))  /* skip leading  space */
  30.         dstr++;
  31.     switch (c) {                /* optional sign */
  32.       case '-':
  33.         neg_val = 1;
  34.       case '+':         /* fall-through */
  35.         dstr++;
  36.     }
  37.  
  38.     if (isdigit(c = *dstr++))
  39.     /* add up converted values before dec point */
  40.         do /* changed from while to do while for optimization */
  41.                 retval = 10 * retval + (double) (c - '0' while (isdigit(c = *dstr++));
  42.     if (c == '.')
  43. #if LDBL_DIG > DBL_DIG
  44.         while (isdigit(c = *dstr++))   /* and after dec pt */
  45.             retval += (c - '0') * dp10_.p[--fdig];
  46. #else
  47.         if (isdigit(c = *dstr++))
  48.             for (;;) {          /* and after dec pt, order of operations
  49.                                    must be as shown */
  50.                 retval = (x = retval) + (r += (c - '0') * dp10_.p[--fdig]);
  51.                 if (!isdigit(c = *dstr++))
  52.                     break;
  53.                 r += x -= retval;     /* numerical error correction term */
  54.             }
  55. #endif
  56.     if ((c | ' ') == 'e') {     /* found an exponent lead-in */
  57.  
  58.         switch (*dstr) {        /* sign field */
  59.           case '-':
  60.             neg_exp = 1;
  61.           case '+':        /* fall-through */
  62.           case ' ':             /* many FORTRAN environments generate this! */
  63.             dstr++;
  64.           default:
  65.             ;            /* fall-through */
  66.         }
  67.         if (isdigit(c = *dstr))        /* found  exponent digit */
  68.             do
  69.                e_exp = 10 * e_exp + (int) (c - '0');
  70.             while (isdigit(c = *++dstr));
  71.     }
  72.     if ((exp += neg_exp ? -e_exp : e_exp) >= 0)
  73.         if (exp <= DBL_MAX_10_EXP)
  74.             retval *= dp10_.p[exp];
  75.         else {
  76.             errno = ERANGE;
  77.             retval = HUGE_VAL;
  78.         }
  79.     else if ((exp = -exp) <= DBL_MAX_10_EXP)
  80.         retval /= dp10_.p[exp];
  81.     else if (exp - DBL_MAX_10_EXP / 2 <= DBL_MAX_10_EXP) {
  82.         retval /= dp10_.p[DBL_MAX_10_EXP / 2];
  83.         retval /= dp10_.p[exp - DBL_MAX_10_EXP / 2];
  84.     } else {
  85.         retval = 0;
  86.         errno = ERANGE;
  87.     }
  88.     return (neg_val ? -retval : retval);        /* apply sign */
  89. }
  90.